// 知识点1：若我们使用一个函数模版初始化一个函数指针或为一个函数指针赋值，编译器会使用指针的类型来推断模版的实参

// int(*p)(const int&,const int&) =
// compare;//compare中的T类型会根据指针的类型决定，变为int
// 知识点2：当一个参数为函数模版的实例的地址时，程序上下文必须满足：对每个模版实参都能唯一确定其类型或值

// 知识点3：当模版参数类型是一个左值引用时(T&)，只能传递给它一个左值（一个变量、一个返回引用类型的表达式），实参可以是const类型，如果实参是const，T将会被推断为const类型

// 知识点4：当模版参数类型是const
// T&时，我们可以传递给它任何类型的实参（一个非const或const的对象、一个临时对象、一个字面常量值），由于参数本身是const，T的推断类型将不会是const类型，const已经是函数参数类型的一部分，所以const将不会出现在T中

// 知识点5：当函数参数为右值引用时（T&&），正常的绑定规则是只能传递右值的（比如：4），但是却又两个例外允许将左值也绑定到右值引用上

// 第一个例外：当我们将一个左值传递给右值引用时，编译器会推断模版参数类型为实参的左值引用类型，即将T推断为T&，以使用左值引用（一般情况下我们不能定义一个引用的引用，但是通过类型别名或者模版参数类型间接定义是可以的）

// 第二个例外：只有四个以上的引用符号会转化为X&&
// &&折叠为X&&，其他都会折叠为普通的左值引用X&

// 知识点6：总结以上：若模版函数参数为右值引用，则可以绑定一个左值，且如果传入实参是左值的话，编译器推断出的模版实参类型将是一个左值的引用，且函数参数将会被实例化一个普通的左值引用类型

// 知识点7：由于对于函数模版参数右值引用可传入左值和右值，左值会将T绑定为int
// &，右值绑定为int，所以这样会对程序造成极大的困难，实际中右值引用常用于两种情况：模版转发其实参或者模版被重载

// 答案：

// (a)：T 为int &，经折叠，val为int &

// (b)：T 为const int & ，经折叠，val为const int &

// (c)：T 为int &&，经折叠，val为int &&